#include "ocl_dl.h"

#if defined(_MACOS)
#	ifndef __KTYPE_H__
#		include "../../Platform/osx/wintypes.h"
#	endif
#elif defined(__ANDROID__)
#	ifndef __KTYPE_H__
#		include "../../Platform/android/wintypes.h"
#	endif
#endif

#define CLRAPI(x) o##x = NULL;
#define DEFAPI(x) t_##x o##x = NULL;
#define GETAPI(x) o##x = (t_##x)GetProcAddress((HINSTANCE)m_dll, (#x));

DEFAPI(clGetPlatformIDs);
DEFAPI(clGetPlatformInfo);
DEFAPI(clGetDeviceIDs);
DEFAPI(clGetDeviceInfo);
DEFAPI(clCreateContext);
DEFAPI(clReleaseContext);
DEFAPI(clCreateCommandQueue);
DEFAPI(clReleaseCommandQueue);
DEFAPI(clRetainKernel);
DEFAPI(clReleaseKernel);
DEFAPI(clSetKernelArg);
DEFAPI(clEnqueueNDRangeKernel);
DEFAPI(clCreateProgramWithSource);
DEFAPI(clBuildProgram);
DEFAPI(clGetProgramBuildInfo);
DEFAPI(clCreateKernelsInProgram);
DEFAPI(clGetKernelInfo);
DEFAPI(clGetKernelWorkGroupInfo);
DEFAPI(clReleaseProgram);
DEFAPI(clCreateBuffer);
DEFAPI(clEnqueueReadBuffer);
DEFAPI(clEnqueueMapBuffer);
DEFAPI(clEnqueueUnmapMemObject);
DEFAPI(clCreateImage2D);
DEFAPI(clEnqueueReadImage);
DEFAPI(clEnqueueMapImage);
DEFAPI(clRetainMemObject);
DEFAPI(clReleaseMemObject);
DEFAPI(clWaitForEvents);
DEFAPI(clGetEventProfilingInfo);
DEFAPI(clReleaseEvent);

oclLoader::~oclLoader()
{
    CLRAPI(clGetPlatformIDs);
    CLRAPI(clGetPlatformInfo);
    CLRAPI(clGetDeviceIDs);
    CLRAPI(clGetDeviceInfo);
    CLRAPI(clCreateContext);
    CLRAPI(clReleaseContext);
    CLRAPI(clCreateCommandQueue);
    CLRAPI(clReleaseCommandQueue);
    CLRAPI(clRetainKernel);
    CLRAPI(clReleaseKernel);
    CLRAPI(clSetKernelArg);
    CLRAPI(clEnqueueNDRangeKernel);
    CLRAPI(clCreateProgramWithSource);
    CLRAPI(clBuildProgram);
    CLRAPI(clGetProgramBuildInfo);
    CLRAPI(clCreateKernelsInProgram);
    CLRAPI(clGetKernelInfo);
    CLRAPI(clGetKernelWorkGroupInfo);
    CLRAPI(clReleaseProgram);
    CLRAPI(clCreateBuffer);
    CLRAPI(clEnqueueReadBuffer);
    CLRAPI(clEnqueueMapBuffer);
    CLRAPI(clEnqueueUnmapMemObject);
    CLRAPI(clCreateImage2D);
    CLRAPI(clEnqueueReadImage);
    CLRAPI(clEnqueueMapImage);
    CLRAPI(clRetainMemObject);
    CLRAPI(clReleaseMemObject);
    CLRAPI(clWaitForEvents);
    CLRAPI(clGetEventProfilingInfo);
    CLRAPI(clReleaseEvent);
    if (m_dll)
    {
#ifndef _METRO
        FreeLibrary((HINSTANCE)m_dll);
#endif
        m_dll = NULL;
    }
}
oclLoader::oclLoader() : m_dll(NULL)
{
#ifndef _METRO
    m_dll = (void*)LoadLibraryA("OpenCL.dll");
    if (m_dll)
    {
        GETAPI(clGetPlatformIDs);
        GETAPI(clGetPlatformInfo);
        GETAPI(clGetDeviceIDs);
        GETAPI(clGetDeviceInfo);
        GETAPI(clCreateContext);
        GETAPI(clReleaseContext);
        GETAPI(clCreateCommandQueue);
        GETAPI(clReleaseCommandQueue);
        GETAPI(clRetainKernel);
        GETAPI(clReleaseKernel);
        GETAPI(clSetKernelArg);
        GETAPI(clEnqueueNDRangeKernel);
        GETAPI(clCreateProgramWithSource);
        GETAPI(clBuildProgram);
        GETAPI(clGetProgramBuildInfo);
        GETAPI(clCreateKernelsInProgram);
        GETAPI(clGetKernelInfo);
        GETAPI(clGetKernelWorkGroupInfo);
        GETAPI(clReleaseProgram);
        GETAPI(clCreateBuffer);
        GETAPI(clEnqueueReadBuffer);
        GETAPI(clEnqueueMapBuffer);
        GETAPI(clEnqueueUnmapMemObject);
        GETAPI(clCreateImage2D);
        GETAPI(clEnqueueReadImage);
        GETAPI(clEnqueueMapImage);
        GETAPI(clRetainMemObject);
        GETAPI(clReleaseMemObject);
        GETAPI(clWaitForEvents);
        GETAPI(clGetEventProfilingInfo);
        GETAPI(clReleaseEvent);
    }
#endif
}